﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using System.Net;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using DataAccess;
using Entities;

namespace Logic
{
	public class MovieBL
	{
		/*public Movie Create(string name, Video videoinfo)
		{
			Movie entity = new Movie();

			entity.Title = name;
			SetData(entity);
			entity.Poster = GetPosterURL(entity);

			return entity;
		}*/

		public Movie Create(Movie entity)
		{
			return SetData(entity);
		}

		public Movie Create(Video videoinfo, bool getData, bool getPoster)
		{
			Movie entity = new Movie();

			entity.VideoInfo = GetVideoData(videoinfo);
			entity.Title = ClearTitle(entity);

			if (getData)
			{
				entity = SetData(entity);
				if (getPoster && entity.Poster == "http://hpneo.com/DoubleFeature/img/poster_default.jpg")
				{
					entity.Poster = GetPosterURL(entity);
				}
			}

			return entity;
		}

		public string ClearTitle(Movie entity)
		{
			String title = "Untitled Movie";
			try
			{
				FileInfo fi = new FileInfo(entity.VideoInfo.FileName);
				title = fi.Name.Replace(fi.Extension, "");

				title = title.Replace(".TS.", "");
				title = title.Replace(".DUBBED.", "");
				title = title.ToLower();
				title = title.Replace(".ts.", " ");
				title = title.Replace(".720p.", " ");
				title = title.Replace(".1080p.", " ");
				title = title.Replace("x264", " ");
				title = title.Replace("bluray", "");
				title = title.Replace("bluray", "");
				title = title.Replace("xvid", "");
				title = title.Replace("divx", "");
				title = title.Replace("bdrip", "");
				title = title.Replace("dvdrip", "");
				title = title.Replace("-vh", "");
				title = title.Replace("arw-", "");
				title = title.Replace("-fxg", "");
				title = title.Replace("-aen", "");
				title = title.Replace("-prod", "");
				title = title.Replace("-lchd", "");
				title = title.Replace("-imbt", "");
				title = title.Replace("-axxo", "");
				title = title.Replace("-lumix", "");
				title = title.Replace("-metis", "");
				title = title.Replace("-arrow", "");
				title = title.Replace("-prism", "");
				title = title.Replace("-vomit", "");
				title = title.Replace("-f!ash", "");
				title = title.Replace("-ch4cal", "");
				title = title.Replace("-nedivx", "");
				title = title.Replace("-devise", "");
				title = title.Replace("-befree", "");
				title = title.Replace("-domino", "");
				title = title.Replace("-swedivx", "");
				title = title.Replace("-foxnews", "");
				title = title.Replace("-refined", "");
				title = title.Replace("-larceny", "");
				title = title.Replace("-saphire", "");
				title = title.Replace("-nodlabs", "");
				title = title.Replace("-thugline", "");
				title = title.Replace("-delethis", "");
				title = title.Replace("-dimension", "");
				title = title.Replace("-stealthmaster", "");

				title = title.Replace("-", " ");
				title = title.Replace("_", " ");
				title = title.Replace(".", " ");

                title = Regex.Replace(title, "cd\\d+$", "");
                title = Regex.Replace(title, "^\\[(?<title>\\w{,5})\\]", " ${title}");
				title = Regex.Replace(title, "\\((?<year>\\d{4})\\)", " ${year}");
				title = Regex.Replace(title, "\\[(?<year>\\d{4})\\]", " ${year}");
				title = Regex.Replace(title, "\\[(\\w?\\s?-?)*\\]", "");
				title = Regex.Replace(title, "-[\\w+\\s?]*$", "");
				title = title.Replace("[", "");
				title = title.Replace("]", "");
				title = title.Trim();

				title = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(title);
			}
			catch (Exception ex)
			{

			}
			return title;
		}

		private string GetPosterFromTheMovieDB(Movie entity)
		{
			String poster = "http://hpneo.com/DoubleFeature/img/poster_default.jpg";
			try
			{
				XmlDocument XMLDoc = new XmlDocument();
				XMLDoc.Load("http://api.themoviedb.org/2.1/Movie.search/en/xml/fdf3c94669f3cc0906fddc99e5cd8208/" + entity.Title);

				XmlNodeList Pelicula = XMLDoc.GetElementsByTagName("movie");
				XmlNodeList Imagen = ((XmlElement)Pelicula[0]).GetElementsByTagName("image");

				for (int i = 0; i < Imagen.Count; i++)
				{
					if (Imagen.Item(i).Attributes["size"].Value == "mid")
					{
						poster = Imagen.Item(i).Attributes["url"].Value;
						break;
					}
					else
						poster = "http://hpneo.com/DoubleFeature/img/poster_default.jpg";
				}
			}
			catch (Exception ex)
			{
				//MessageBox.Show("Error at getPosterFromTheMovieDB: " + ex.Message);
				poster = "http://hpneo.com/DoubleFeature/img/poster_default.jpg";
			}

			return poster;
		}

		public string GetPosterURL(Movie entity)
		{
			String poster = "";
			try
			{
				if (entity.Poster == "http://hpneo.com/DoubleFeature/img/poster_default.jpg")
				{
					string URL = "http://www.google.com/cse?cx=partner-pub-6811780361519631%3A48v46vdqqnk&cof=FORID%3A9&ie=ISO-8859-1&q=" + entity.Title;
					StreamReader sr = new StreamReader(new WebClient().OpenRead(URL));
					string content = sr.ReadToEnd();
					Regex re = new Regex("http://www\\.impawards.com/\\d{4,4}/(_?\\w*)*\\.html", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
					if (re.Matches(content).Count > 0)
					{
						string[] match_url = re.Matches(content)[0].Value.Replace("http://", "").Replace(".html", ".jpg").Split('/');
						string poster_url = "http://" + match_url[0] + "/" + match_url[1] + "/posters/" + match_url[2];

						if (poster_url.Contains("std.jpg"))
							GetPosterFromTheMovieDB(entity);
						else
							poster = poster_url;
					}
					else
					{
						GetPosterFromTheMovieDB(entity);
					}
				}
			}
			catch (Exception ex)
			{
				//MessageBox.Show("Error at getPoster: " + ex.Message);
				poster = "http://hpneo.com/DoubleFeature/img/poster_default.jpg";
			}

			return poster;
		}

		private string SetPoster(Movie entity, int _width)
		{
			try
			{
				if (entity.Poster == "")
					entity.Poster = "http://hpneo.com/DoubleFeature/img/poster_default.jpg";

				Image image;
				Stream stream;

				if (entity.Poster.Contains("http://"))
					stream = System.Net.WebRequest.Create(entity.Poster).GetResponse().GetResponseStream();
				else
					stream = File.Open(entity.Poster, FileMode.Open, FileAccess.Read, FileShare.Delete);

				image = Image.FromStream(stream);

				stream.Close();

				int sourceWidth = image.Width;
				int sourceHeight = image.Height;

				int destWidth = 0;
				int destHeight = 0;

				if (sourceWidth > sourceHeight)
				{
					destWidth = (int)(_width) * 2;
					destHeight = (int)((_width * sourceHeight) / sourceWidth) * 2;
				}
				else
				{
					destWidth = (int)(_width);
					destHeight = (int)((_width * sourceHeight) / sourceWidth);
				}

				Image thumbnail = new Bitmap(destWidth, destHeight);

				Graphics graphic = Graphics.FromImage(thumbnail);
				graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
				graphic.SmoothingMode = SmoothingMode.HighQuality;
				graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
				graphic.DrawImage(image, 0, 0, destWidth, destHeight);
				EncoderParameters Params = new EncoderParameters(1);
				Params.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 80L);
				ImageCodecInfo[] Info = ImageCodecInfo.GetImageEncoders();

				entity.Poster = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + "\\Movies Posters\\" + DateTime.Now.Ticks.ToString() + "_" + DateTime.Now.Millisecond.ToString() + ".jpg";

				thumbnail.Save(entity.Poster, Info[1], Params);

				return entity.Poster;
			}
			catch (Exception e)
			{
				return "";
				//System.Windows.Forms.MessageBox.Show("Error at ResizeCover method: " + e.Message);
			}
		}

		private string SetPoster(Movie entity, string posterpath, int _width)
		{
			try
			{
				Image image;

				if (posterpath == "")
					image = Properties.Resources.poster_default;
				else
					image = Image.FromFile(posterpath);

				int sourceWidth = image.Width;
				int sourceHeight = image.Height;

				int destWidth = 0;
				int destHeight = 0;

				if (sourceWidth > sourceHeight)
				{
					destWidth = (int)(_width) * 2;
					destHeight = (int)((_width * sourceHeight) / sourceWidth) * 2;
				}
				else
				{
					destWidth = (int)(_width);
					destHeight = (int)((_width * sourceHeight) / sourceWidth);
				}

				Image thumbnail = new Bitmap(destWidth, destHeight);

				Graphics graphic = Graphics.FromImage(thumbnail);
				graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
				graphic.SmoothingMode = SmoothingMode.HighQuality;
				graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
				graphic.DrawImage(image, 0, 0, destWidth, destHeight);
				EncoderParameters Params = new EncoderParameters(1);
				Params.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 80L);
				ImageCodecInfo[] Info = ImageCodecInfo.GetImageEncoders();

				entity.Poster = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + "\\Movies Posters\\" + DateTime.Now.Ticks.ToString() + "_" + DateTime.Now.Millisecond.ToString() + ".jpg";

				thumbnail.Save(entity.Poster, Info[1], Params);

				return entity.Poster;
			}
			catch (Exception e)
			{
				return "";
				//System.Windows.Forms.MessageBox.Show("Error at ResizeCover method: " + e.Message);
			}
		}

		private Movie SetData(Movie entity)
		{
			try
			{
				switch (Properties.Settings.Default.InfoProvider)
				{
					/*case InfoProvider.FilmAffinity:
						FilmAffinityScrapper FA = new FilmAffinityScrapper();

						Movie aux = FA.GetMovieInfo(entity.Title);
						if (aux != null)
						{
							entity.Title = aux.Title;
							entity.Year = aux.Year;
							entity.Director = aux.Director;
							entity.Genres = aux.Genres;
							entity.Poster = aux.Poster;
						}
						break;*/
					case InfoProvider.TheMovieDB:
						TMDBAPI TMDBAPI = new TMDBAPI("fdf3c94669f3cc0906fddc99e5cd8208");
						List<Movie> moviesaux = TMDBAPI.SearchMovies(entity.Title, Properties.Settings.Default.SeekOriginalName);
						if (moviesaux.Count > 0)
						{
							entity.Title = moviesaux[0].Title;
							entity.Year = moviesaux[0].Year;
							entity.Director = moviesaux[0].Director;
							entity.Genres = moviesaux[0].Genres;
							entity.Poster = moviesaux[0].Poster;
						}
						break;
				}
			}
			catch (Exception ex)
			{
				//MessageBox.Show("Error at getData: " + ex.Message);
				entity.Title = ClearTitle(entity);
				entity.Year = 0;
				entity.Director = "";
				entity.Genres = new List<Genre>();
				entity.Poster = "http://hpneo.com/DoubleFeature/img/poster_default.jpg";
			}
			return entity;
		}

		public Video GetVideoData(Video entity)
		{
			try
			{
				Process p = new Process();
				p.StartInfo.FileName = "Resources\\ffmpeg.exe";
				p.StartInfo.Arguments = "-i \"" + entity.FileName + "\"";
				p.StartInfo.UseShellExecute = false;
				p.StartInfo.ErrorDialog = false;
				p.StartInfo.CreateNoWindow = true;
				p.StartInfo.RedirectStandardOutput = true;
				p.StartInfo.RedirectStandardError = true;
				p.Start();
				string data = p.StandardError.ReadToEnd();

				string durationPattern = "Duration: .{9}";
				string typePattern = "0, .{3,6},";
				string sizePattern = "\\d{3,5}x\\d{3,5}";
				Regex re = new Regex(durationPattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
				if (re.Matches(data).Count > 0)
				{
					entity.Duration = re.Matches(data)[0].Value.Replace("Duration: ", "");
				}
				re = new Regex(sizePattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
				if (re.Matches(data).Count > 0)
				{
					entity.Width = Convert.ToInt32(re.Matches(data)[0].Value.Split('x')[0]);
					entity.Height = Convert.ToInt32(re.Matches(data)[0].Value.Split('x')[1]);
				}
				re = new Regex(typePattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
				if (re.Matches(data).Count > 0)
				{
					entity.Type = re.Matches(data)[0].Value.Replace(",", "").Replace("0", "").Trim();
				}
			}
			catch (Exception e) { }

			return entity;
		}

		public List<Movie> GetSuggestions(Movie entity)
		{
			List<Movie> suggestions = new List<Movie>();

			switch (Properties.Settings.Default.InfoProvider)
			{
				/*case InfoProvider.FilmAffinity:
					FilmAffinityScrapper fa = new FilmAffinityScrapper();
					suggestions = fa.GetMoviesSuggestions(entity.Title);
					break;*/
				case InfoProvider.TheMovieDB:
					TMDBAPI tmdb = new TMDBAPI("fdf3c94669f3cc0906fddc99e5cd8208");
					suggestions = tmdb.SearchMovies(entity.Title, Properties.Settings.Default.SeekOriginalName);
					break;
			}
			return suggestions;
		}

		public List<Movie> GetLastMovies(int number)
		{
			MovieDAL dal = new MovieDAL();
			return dal.List("SELECT * FROM movies ORDER BY movie_id DESC LIMIT "+number);
		}

		public List<Movie> Search(string title)
		{
			MovieDAL dal = new MovieDAL();
			return dal.Search(title);
		}

		public List<Movie> ListMoviesOldWay()
		{
			MovieDAL dal = new MovieDAL();
			return dal.ListMoviesOldWay();
		}

        public List<MovieList> GetListsByMovie(Movie entity, bool isin)
        {
            MovieDAL dal = new MovieDAL();
            return dal.GetListsByMovie(entity, isin);
        }

		public bool ChangePoster(Movie entity, string newposterpath)
		{
			try
			{
				Properties.Settings.Default.PostersToDelete.Add(entity.Poster);
				Properties.Settings.Default.Save();

				entity.Poster = newposterpath;

				SetPoster(entity, 350);

				MovieDAL dal = new MovieDAL();

				return dal.UpdatePosterPath(entity);
			}
			catch (Exception e)
			{
				return false;
			}
		}

		public bool ChangeLocation(Movie entity, string[] paths)
		{
			string path = String.Join("|", paths);

			entity.VideoInfo.FileName = path;

			MovieDAL dal = new MovieDAL();

			return dal.UpdatePath(entity);
		}

		public bool UpdateViews(Movie entity)
		{
			MovieDAL dal = new MovieDAL();
			return dal.UpdateViews(entity);
		}

		public bool UpdateGenres(Movie entity)
		{
			MovieDAL dal = new MovieDAL();
			return dal.UpdateGenres(entity);
		}

		public bool UpdateTags(Movie entity)
		{
			MovieDAL dal = new MovieDAL();
			return dal.UpdateTags(entity);
		}

		public bool UpdateRating(Movie entity)
		{
			MovieDAL dal = new MovieDAL();
			return dal.UpdateRating(entity);
		}

		public void RenameTitle(Movie entity, string newformat)
		{
			string title = newformat;

			title = title.Replace("{title}", entity.Title);
			title = title.Replace("{year}", entity.Year.ToString());
			title = title.Replace("{director}", entity.Director);

			entity.Title = title;

			MovieDAL dal = new MovieDAL();
			dal.RenameTitle(entity);
		}

		public bool Save(Movie entity)
		{
			SetPoster(entity, 350);
			MovieDAL dal = new MovieDAL();
			dal.Save(entity);

			if (entity.Id > 0)
				return true;
			else
				return false;
		}

		public bool Update(Movie entity)
		{
			MovieDAL dal = new MovieDAL();
			return dal.Update(entity);
		}

		public bool Delete(Movie entity)
		{
			MovieDAL dal = new MovieDAL();
			if (dal.Delete(entity))
			{
				Logic.Properties.Settings.Default.PostersToDelete.Add(entity.Poster);
				Logic.Properties.Settings.Default.Save();
				return true;
			}
			else
			{
				return false;
			}
		}

		public bool AddGenre(Movie entity, Genre genre)
		{
			MovieDAL dal = new MovieDAL();
			return dal.AddGenre(entity, genre);
		}

		public void Play(Movie entity)
		{
			MovieDAL dal = new MovieDAL();
			entity.Views = entity.Views + 1;
			dal.UpdateViews(entity);

			string[] filenames = entity.VideoInfo.FileName.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);

			for (int i = 0; i < filenames.Length; i++)
			{
				if (File.Exists(filenames[i]))
					filenames[i] = "\"" + filenames[i] + "\"";
				else
					filenames[i] = "";

				filenames[i].Trim();
			}

			System.Diagnostics.Process p = new System.Diagnostics.Process();
			p.StartInfo.FileName = Properties.Settings.Default.PlayerPath;
			p.StartInfo.Arguments = String.Join(" ", filenames);
			if (Properties.Settings.Default.PlayerPath.Contains("vlc.exe"))
			{
				p.StartInfo.Arguments += " -f";
			}
			else if (Properties.Settings.Default.PlayerPath.Contains("mplayer.exe"))
			{
				p.StartInfo.Arguments += " -fs";
			}
			p.Start();
		}

		public void MoveTo(Movie entity, string newDirectory)
		{
			string[] paths = entity.VideoInfo.FileName.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);

			List<string> newpaths = new List<string>();

			foreach (string path in paths)
			{
				string newfilename;

				if (File.Exists(path))
				{
					FileInfo info = new FileInfo(path);
					newfilename = Path.Combine(newDirectory, info.Name);
					info.MoveTo(newfilename);
				}
				else
				{
					newfilename = path;
				}

				newpaths.Add(newfilename);
			}

			entity.VideoInfo.FileName = String.Join("|", newpaths.ToArray());

			MovieDAL dal = new MovieDAL();

			dal.UpdatePath(entity);
		}

		public void ShowInExplorer(Movie entity)
		{
			string[] paths = entity.VideoInfo.FileName.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string path in paths)
			{
				if (File.Exists(path))
				{
					System.Diagnostics.Process p = new System.Diagnostics.Process();
					p.StartInfo.FileName = "explorer";
					p.StartInfo.Arguments = "/select," + path;
					p.Start();
				}
			}
		}
	}
}